import json
import logging
import os

from references_process.config import JSON_REFERENCES_FILE_PATH


def setup_logger():
    """
    Set up the logger.
    :return: Configured logger
    """
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
    logger.addHandler(handler)
    return logger


class CalculateJson:
    """Class to process and analyze JSON files."""

    def __init__(self, directory_path):
        self.directory_path = directory_path
        self.logger = setup_logger()
        self.total_articles = 0
        self.total_references = 0

    def list_json_files(self):
        """
        List all JSON files in the directory.
        :return: List of JSON file paths
        """
        return [os.path.join(self.directory_path, file) for file in os.listdir(self.directory_path) if file.endswith('.json')]

    def load_data(self, file_path):
        """
        Load JSON data from a file.
        :param file_path: Path to the JSON file
        :return: Loaded JSON data
        """
        with open(file_path, "r", encoding="utf-8") as f:
            return json.load(f)

    def count_articles(self, data):
        """
        Count the number of articles in the JSON data.
        :param data: JSON data
        """
        num_articles = len(data.keys())
        self.total_articles += num_articles
        self.logger.info("Total number of articles in this file: %d", num_articles)

    def count_references_per_article(self, data):
        """
        Count the number of references in each article.
        :param data: JSON data
        """
        references_count = {title: len(article["references"]) for title, article in data.items()}
        sorted_references_count = dict(sorted(references_count.items(), key=lambda x: x[1], reverse=True))
        for title, count in list(sorted_references_count.items())[:10]:
            print(f"{title}: {count}")
        self.total_references += sum(references_count.values())

    def find_articles_with_no_references(self, data):
        """
        Find articles with no references.
        :param data: JSON data
        """
        no_references = [title for title, article in data.items() if not article["references"]]
        self.logger.info("Total number of articles with no references: %d", len(no_references))

        with open("empty_titles.txt", "w", encoding="utf-8") as f:
            f.write(f"TI=({' + '.join(no_references)})")

    def count_reference_types(self, data):
        """
        Count the number of references of different types.
        :param data: JSON data
        """
        total = 0
        counts = {
            "[J]": 0,
            "[M]": 0,
            "[N]": 0,
            "[D]": 0,
            "[S]": 0,
            "[A]": 0,
            "[R/OL]": 0,
            "other": 0,
        }
        for article in data.values():
            for ref in article["references"]:
                total += 1
                for key in counts:
                    if key in ref:
                        counts[key] += 1
                        break
                else:
                    counts["other"] += 1

        print(f"Total: {total}")
        for category, count in counts.items():
            percentage = round((count / total) * 100, 2)
            print(f"{category}: {count}, Account for {percentage} %")

    def process_all_files(self):
        """
        Process all JSON files in the directory.
        """
        json_files = self.list_json_files()
        for file_path in json_files:
            self.logger.info(f"Processing file: {file_path}")
            data = self.load_data(file_path)
            self.count_articles(data)
            self.count_references_per_article(data)
            self.find_articles_with_no_references(data)
            self.count_reference_types(data)
        self.logger.info("Total number of articles: %d", self.total_articles)
        self.logger.info("Total number of references: %d", self.total_references)


def main():
    """
    Main function to process JSON files in a directory.
    """
    directory_path = JSON_REFERENCES_FILE_PATH
    cal = CalculateJson(directory_path)
    cal.process_all_files()


if __name__ == "__main__":
    main()
